package ru.ifmo.automaton.generators.fixed;

import org.uncommons.maths.number.ConstantGenerator;
import org.uncommons.maths.number.NumberGenerator;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author avhaliullin
 */
public class CernyAutomatonSource
        extends AbstractFixedAutomatonSource<Character, String>
        implements StatesCountDependedObject {

    private static final Character CHAR_A = 'a';
    private static final Character CHAR_B = 'b';
    private static final List<Character> alphabet;

    static {
        alphabet = new ArrayList<Character>();
        alphabet.add(CHAR_A);
        alphabet.add(CHAR_B);
    }

    private Map<String, Map<Character, String>> transitions;


    private NumberGenerator<Integer> statesCountGenerator = new ConstantGenerator<Integer>(10);
    private int statesCount = -1;

    private static String state(int state) {
        return String.valueOf(state);
    }

    @Override
    protected void rebuildIfNeed() {
        if (statesCountGenerator.nextValue() != statesCount) {
            statesCount = statesCountGenerator.nextValue();

            transitions = new HashMap<String, Map<Character, String>>();
            for (int i = 0; i < statesCount; i++) {
                String state = state(i);
                Map<Character, String> trans = new HashMap<Character, String>();
                transitions.put(state, trans);

                if (i == statesCount - 1) {
                    trans.put(CHAR_A, state(0));
                    trans.put(CHAR_B, state(0));
                } else {
                    trans.put(CHAR_A, state(i + 1));
                    trans.put(CHAR_B, state(i));
                }
            }

        }

    }

    @Override
    protected int getMswLength() {
        return (statesCount - 1) * (statesCount - 1);
    }

    @Override
    protected List<Character> getAlphabet() {
        return alphabet;
    }

    @Override
    protected String getInitial() {
        return state(0);
    }

    @Override
    protected Map<String, Map<Character, String>> getTransitions() {
        return transitions;
    }

    public void setStatesCount(NumberGenerator<Integer> statesCount) {
        this.statesCountGenerator = statesCount;
    }

}
